/**
 * Copyright (C) 2012 The SkyTvOS Project
 *
 * Version     Date           Author
 * ─────────────────────────────────────
 *           2015-12-16         yellowlgx
 *
 */

package com.skyworth.ui.listview;

import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import com.skyworth.ui.customview.SlideFocusView.FocusChangedEvent;
import com.skyworth.ui.customview.SlideFocusView.FocusViewRevision;

import java.util.List;

/**
 * @ClassName MetroAdapter
 * @Description 通用泛型Adapter，可以继承，也可直接使用(推荐直接new使用)<br>
 *              配合MetroListview使用，也可直接用于android提供的listView/GridView <br>
 *              其中数据类型由使用者自定义
 * @author yellowlgx
 * @date 2015-12-16
 */
public abstract class MetroAdapter<T> extends BaseAdapter implements IAdapter<T>
{
    /**
     * @Fields mDataList 泛型数据，外部控制
     */
    private List<T> mDataList;

    private ItemTypeUtil util;

    /**
     * @Fields mViewTypeCount item的类型总数
     */
    private int mViewTypeCount = 1;

    /**
     * @Fields mViewType 每个item的类型，会根据每一条数据进行产生
     */
    private Object mViewType;

    /**
     * @Fields mObserver 观察者，用于更新数据后刷新UI
     */
    protected ObserverListener mObserver = null;

    /**
     * @Fields focusChangedEvent 公共焦点移动监听
     */
    protected FocusChangedEvent focusChangedEvent;
    private FocusViewRevision focusViewRevision;
    private OnFocusChangeListener focusChangeListener;

    public static boolean onChangeNeedClearFlag = true;

    /**
     * @ClassName ObserverListener
     * @Description 观察者模式接口<br/>
     */
    public interface ObserverListener
    {
        public void onChanaged();

        public void onChanagedTotal();

        public void onChanagedAll();
    }

    protected MetroAdapter(List<T> data)
    {
        this(data, 1);
    }

    protected MetroAdapter(List<T> data, int viewTypeCount)
    {
        mDataList = data;
        mViewTypeCount = viewTypeCount;
        util = new ItemTypeUtil();
    }

    /**
     * @Description 用于重新设置Adapter的数据，并对UI进行刷新<br/>
     * @param data
     *            void
     * @date 2016-3-3
     */
    public void changeData(List<T> data)
    {
        mDataList = data;
        notifyDataSetChanagedAll();
    }

    /**
     * @Description 用于使用公共焦点移动框，注册监听<br/>
     * @param focusChangedEvent
     *            监听注册
     * @param rev
     *            焦点框上下左右位置
     * @param focusChangeListener
     *            外部焦点监听回调
     * @date 2016-1-4
     */
    public void setFocusChangedEvent(FocusChangedEvent focusChangedEvent, FocusViewRevision rev,
            OnFocusChangeListener focusChangeListener)
    {
        this.focusChangedEvent = focusChangedEvent;
        this.focusViewRevision = rev;
        this.focusChangeListener = focusChangeListener;
    }

    /**
     * 注册观察者，发现有数据变化，就通知刷新
     * 
     * @param listener
     */
    public void registObserver(ObserverListener listener)
    {
        mObserver = listener;
    }

    @Override
    public List<T> getData()
    {
        return mDataList;
    }

    @Override
    public int getCount()
    {
        return mDataList != null ? mDataList.size() : 0;
    }

    @Override
    public T getItem(int position)
    {
        if (mDataList == null || mDataList.size() <= 0 || position < 0
                || position >= mDataList.size())
        {
            return null;
        }
        return mDataList.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public Object getItemType(T t)
    {
        return -1;
    }

    /**
     * 通过数据得到obj的类型的type 然后，通过{@link ItemTypeUtil}来转换位int类型的type
     * 
     * instead by{@link #getItemType(Object)}
     */
    @Override
    public int getItemViewType(int position)
    {
        if (mDataList != null && mDataList.size() > position)
            mViewType = getItemType(mDataList.get(position));
        else
            mViewType = -1;
        // 如果不写这个方法，会让listView更换dataList后无法刷新数据
        return util.getIntType(mViewType);
    }

    @Override
    public int getViewTypeCount()
    {
        return mViewTypeCount;
    }

    @SuppressWarnings("unchecked")
    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        AdapterItem<T> item = null;
        int viewType = getItemViewType(position);
        if (convertView == null)
        {
            item = onCreateItem(mViewType);
            convertView = item.getLayout();
            convertView.setTag(item);
            if (focusChangedEvent != null)
                focusChangedEvent.registerView(convertView, focusViewRevision, focusChangeListener);
        } else
        {
            item = (AdapterItem<T>) convertView.getTag();
        }
        item.clearItem();
        if (mDataList != null && mDataList.size() > position)
            item.onUpdateItemValue(mDataList.get(position), position, viewType);
        return convertView;
    }

    /**
     * 通知开始刷新界面，此方法是刷新当前数据，并不会对改变别的属性
     */
    public void notifyDataSetChanaged()
    {
        if (mObserver != null)
        {
            mObserver.onChanaged();
        }
    }

    /**
     * 通知开始刷新界面,刷新新的数据，此方法用于重新设置数据后的刷新
     */
    public void notifyDataSetChanagedAll()
    {
        if (mObserver != null)
        {
            mObserver.onChanagedAll();
        }
    }

    /**
     * 通知开始刷新界面,刷新数据总数，此方法用于改变了数据总数后的刷新
     */
    public void notifyDataSetChanagedTotal()
    {
        if (mObserver != null)
        {
            mObserver.onChanagedTotal();
        }
    }

}
